#!/bin/bash

# 加载路径配置
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../config/paths.conf"

# 配置文件路径
CONFIG_FILE="$CONFIG_DIR/oss_config"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

warn() {
    echo -e "${YELLOW}[警告]${NC} $1"
}

error() {
    echo -e "${RED}[错误]${NC} $1"
}

# 加载OSS配置
load_oss_config() {
    if [ ! -f "$CONFIG_FILE" ]; then
        error "OSS配置文件不存在: $CONFIG_FILE"
        error "请先运行: $SCRIPTS_DIR/init_oss_config.sh init"
        return 1
    fi
    
    # 检查文件权限
    local file_perm=$(stat -c %a "$CONFIG_FILE" 2>/dev/null || echo "644")
    if [ "$file_perm" -gt 600 ]; then
        warn "OSS配置文件权限过于宽松 ($file_perm)，建议设置为600"
    fi
    
    # 安全地加载配置，避免执行恶意代码
    if ! source "$CONFIG_FILE" 2>/dev/null; then
        error "加载OSS配置失败，请检查配置文件语法"
        return 1
    fi
    
    # 验证必要配置
    local missing_fields=()
    [ -z "$OSS_BUCKET" ] && missing_fields+=("OSS_BUCKET")
    [ -z "$OSS_ENDPOINT" ] && missing_fields+=("OSS_ENDPOINT")
    [ -z "$OSS_ACCESS_KEY_ID" ] && missing_fields+=("OSS_ACCESS_KEY_ID")
    [ -z "$OSS_ACCESS_KEY_SECRET" ] && missing_fields+=("OSS_ACCESS_KEY_SECRET")
    
    if [ ${#missing_fields[@]} -gt 0 ]; then
        error "OSS配置不完整，缺少以下字段: ${missing_fields[*]}"
        return 1
    fi
    
    # 检查是否为示例值
    if [ "$OSS_ACCESS_KEY_ID" = "your-access-key-id" ] || \
       [ "$OSS_ACCESS_KEY_SECRET" = "your-access-key-secret" ]; then
        error "请配置真实的AccessKey，而不是使用示例值"
        error "运行: $SCRIPTS_DIR/init_oss_config.sh edit"
        return 1
    fi
    
    # 设置默认值（如果未在配置文件中设置）
    MAX_UPLOAD_RETRY=${MAX_UPLOAD_RETRY:-3}
    UPLOAD_TIMEOUT=${UPLOAD_TIMEOUT:-300}
    COMPRESSION_ENABLED=${COMPRESSION_ENABLED:-true}
    DELETE_AFTER_UPLOAD=${DELETE_AFTER_UPLOAD:-false}
    OSS_PREFIX=${OSS_PREFIX:-"traffic-monitor"}
    
    return 0
}

# 生成唯一实例标识符
get_instance_id() {
    # 尝试获取ECS实例ID
    if curl -s --connect-timeout 2 http://100.100.100.200/latest/meta-data/instance-id > /dev/null 2>&1; then
        INSTANCE_ID=$(curl -s http://100.100.100.200/latest/meta-data/instance-id 2>/dev/null)
    elif curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/instance-id > /dev/null 2>&1; then
        INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null)
    else
        # 生成基于主机信息的唯一ID
        LOCAL_IP=$(hostname -I | awk '{print $1}')
        MAC_ADDR=$(cat /sys/class/net/$(ip route show default 2>/dev/null | awk '/default/ {print $5}' 2>/dev/null)/address 2>/dev/null | tr -d ':' | tail -c 6)
        INSTANCE_ID="ecs-${LOCAL_IP//./-}-${MAC_ADDR:-$(hostname)}"
    fi
    echo "${INSTANCE_ID}"
}

# 验证文件类型
validate_file_type() {
    local file_path=$1
    
    # 检查文件是否存在
    if [ ! -f "$file_path" ]; then
        error "文件不存在: $file_path"
        return 1
    fi
    
    # 检查文件大小
    local file_size=$(stat -c %s "$file_path" 2>/dev/null || echo "0")
    if [ "$file_size" -eq 0 ]; then
        warn "文件大小为0: $file_path"
    fi
    
    # 检查文件扩展名
    local filename=$(basename "$file_path")
    if [[ "$filename" =~ \.pcap[0-9]*$ ]]; then
        log "检测到PCAP文件: $filename"
        # 检查文件内容是否为PCAP格式（如果file命令可用）
        if command -v file &> /dev/null; then
            local file_type=$(file -b "$file_path" 2>/dev/null)
            if [[ "$file_type" == *"pcap"* ]] || [[ "$file_type" == *"tcpdump"* ]]; then
                log "✓ 验证为PCAP格式文件"
                return 0
            else
                warn "文件内容可能不是PCAP格式: $file_type"
            fi
        fi
        return 0
    elif [[ "$filename" =~ \.(json|log|txt|csv)$ ]]; then
        log "检测到日志/报告文件: $filename"
        return 0
    else
        warn "未知文件类型: $filename"
        return 0  # 不阻止上传，但给出警告
    fi
}

# 清理文件名
clean_filename() {
    local filename=$1
    # 处理PCAP分割文件，保持原扩展名以便识别
    # 但确保文件名格式统一
    echo "$filename" | sed 's/[^a-zA-Z0-9._-]/_/g'
}

# 构建ossutil命令
build_ossutil_cmd() {
    local base_cmd="ossutil"
    
    # 检查ossutil是否可用
    if ! command -v ossutil &> /dev/null; then
        error "ossutil 未安装，请先运行: $SCRIPTS_DIR/init_oss_config.sh install"
        return 1
    fi
    
    # 添加认证参数（只在有安全令牌时添加--sts-token）
    if [ -n "$OSS_SECURITY_TOKEN" ]; then
        base_cmd="$base_cmd -e $OSS_ENDPOINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET --sts-token $OSS_SECURITY_TOKEN"
    else
        base_cmd="$base_cmd -e $OSS_ENDPOINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET"
    fi
    
    echo "$base_cmd"
}

# 上传文件到OSS
upload_file() {
    local file_path=$1
    local instance_id=$(get_instance_id)
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local random_suffix=$(head /dev/urandom 2>/dev/null | tr -dc A-Za-z0-9 | head -c 8 2>/dev/null || echo "fallback")
    
    if [ ! -f "$file_path" ]; then
        error "文件不存在: $file_path"
        return 1
    fi
    
    # 验证文件类型
    if ! validate_file_type "$file_path"; then
        warn "文件验证失败，但仍尝试上传..."
    fi
    
    if ! load_oss_config; then
        return 1
    fi
    
    # 清理文件名并构建OSS路径
    local original_filename=$(basename "$file_path")
    local clean_name=$(clean_filename "$original_filename")
    
    # 简化OSS路径结构：前缀/实例ID/年/月/日/时间戳_随机后缀_文件名
    local oss_path="${OSS_PREFIX}/${instance_id}/$(date +%Y/%m/%d)/${timestamp}_${random_suffix}_${clean_name}"
    
    log "上传文件: $file_path"
    log "目标路径: oss://$OSS_BUCKET/$oss_path"
    
    local ossutil_cmd
    if ! ossutil_cmd=$(build_ossutil_cmd); then
        return 1
    fi
    
    local retry_count=0
    local upload_success=false
    
    # 重试机制
    while [ $retry_count -lt $MAX_UPLOAD_RETRY ] && [ "$upload_success" = "false" ]; do
        log "上传尝试 $((retry_count + 1))/$MAX_UPLOAD_RETRY..."
        
        if timeout $UPLOAD_TIMEOUT $ossutil_cmd cp "$file_path" "oss://$OSS_BUCKET/$oss_path" 2>&1; then
            log "✓ 上传成功"
            upload_success=true
            
            # 上传成功后是否删除本地文件
            if [ "$DELETE_AFTER_UPLOAD" = "true" ]; then
                if rm -f "$file_path"; then
                    log "已删除本地文件: $file_path"
                else
                    warn "删除本地文件失败: $file_path"
                fi
            fi
            
        else
            retry_count=$((retry_count + 1))
            if [ $retry_count -lt $MAX_UPLOAD_RETRY ]; then
                local wait_time=$((UPLOAD_TIMEOUT * retry_count))
                warn "上传失败，${wait_time}秒后重试..."
                sleep $wait_time
            else
                error "上传失败: 超过最大重试次数"
            fi
        fi
    done
    
    if [ "$upload_success" = "true" ]; then
        return 0
    else
        return 1
    fi
}

# 上传整个目录
upload_directory() {
    local dir_path=$1
    
    if [ ! -d "$dir_path" ]; then
        error "目录不存在: $dir_path"
        return 1
    fi
    
    if ! load_oss_config; then
        return 1
    fi
    
    local instance_id=$(get_instance_id)
    local timestamp=$(date +%Y%m%d_%H%M%S)
    # 简化目录路径，去掉随机字符串
    local oss_base_path="${OSS_PREFIX}/${instance_id}/$(date +%Y/%m/%d)/${timestamp}_$(basename "$dir_path")"
    
    log "开始上传目录: $dir_path"
    log "目标基础路径: oss://$OSS_BUCKET/$oss_base_path"
    
    local total_files=0
    local success_files=0
    
    # 查找并上传所有文件
    while IFS= read -r -d '' file; do
        total_files=$((total_files + 1))
        local random_suffix=$(head /dev/urandom 2>/dev/null | tr -dc A-Za-z0-9 | head -c 6 2>/dev/null || echo "fallback")
        local relative_path=${file#$dir_path/}
        local clean_relative_path=$(clean_filename "$relative_path")
        local oss_path="$oss_base_path/${clean_relative_path}"
        
        log "上传 [$total_files]: $file -> oss://$OSS_BUCKET/$oss_path"
        
        # 验证文件类型
        if validate_file_type "$file"; then
            local ossutil_cmd
            if ossutil_cmd=$(build_ossutil_cmd); then
                if $ossutil_cmd cp "$file" "oss://$OSS_BUCKET/$oss_path" 2>/dev/null; then
                    log "✓ 上传成功: $(basename "$file")"
                    success_files=$((success_files + 1))
                    
                    # 上传成功后是否删除本地文件
                    if [ "$DELETE_AFTER_UPLOAD" = "true" ]; then
                        rm -f "$file"
                    fi
                else
                    warn "上传失败: $(basename "$file")"
                fi
            fi
        else
            warn "跳过文件验证失败: $(basename "$file")"
        fi
    done < <(find "$dir_path" -type f -print0)
    
    log "目录上传完成: 成功 $success_files/$total_files 个文件"
    
    if [ $success_files -eq $total_files ]; then
        return 0
    else
        return 1
    fi
}

# 显示配置信息（隐藏敏感信息）
show_config() {
    if ! load_oss_config; then
        return 1
    fi
    
    log "OSS配置信息:"
    echo "=========================================="
    echo "Bucket: $OSS_BUCKET"
    echo "Endpoint: $OSS_ENDPOINT"
    echo "Prefix: $OSS_PREFIX"
    echo "AccessKey ID: ${OSS_ACCESS_KEY_ID:0:8}****"
    echo "Security Token: ${OSS_SECURITY_TOKEN:+"已设置"}"
    echo "最大重试: $MAX_UPLOAD_RETRY"
    echo "超时时间: $UPLOAD_TIMEOUT 秒"
    echo "压缩启用: $COMPRESSION_ENABLED"
    echo "上传后删除: $DELETE_AFTER_UPLOAD"
    echo "=========================================="
}

# 检查ossutil工具
check_oss_util() {
    if command -v ossutil &> /dev/null; then
        log "✓ ossutil 已安装: $(ossutil version 2>/dev/null || echo "未知版本")"
        return 0
    else
        error "ossutil 未安装"
        return 1
    fi
}

# 显示实例信息
show_instance_info() {
    local instance_id=$(get_instance_id)
    log "实例信息:"
    echo "=========================================="
    echo "实例ID: $instance_id"
    echo "主机名: $(hostname)"
    echo "IP地址: $(hostname -I | awk '{print $1}')"
    echo "系统时间: $(date)"
    echo "=========================================="
}

# 测试OSS连接
test_oss_connection() {
    if ! load_oss_config; then
        return 1
    fi
    
    if ! check_oss_util; then
        return 1
    fi
    
    log "测试OSS连接..."
    
    # 创建测试文件
    local test_file="$TEMP_DIR/oss_test_$(date +%s).txt"
    echo "OSS connection test - $(date)" > "$test_file"
    echo "Instance: $(get_instance_id)" >> "$test_file"
    echo "Hostname: $(hostname)" >> "$test_file"
    
    local ossutil_cmd
    if ! ossutil_cmd=$(build_ossutil_cmd); then
        rm -f "$test_file"
        return 1
    fi
    
    local test_path="${OSS_PREFIX}/test/$(get_instance_id)/test_$(date +%Y%m%d_%H%M%S).txt"
    
    log "测试上传: $test_file -> oss://$OSS_BUCKET/$test_path"
    
    if $ossutil_cmd cp "$test_file" "oss://$OSS_BUCKET/$test_path" 2>&1; then
        log "✓ OSS连接测试成功"
        
        # 可选：测试下载
        log "测试下载..."
        local download_file="$TEMP_DIR/oss_test_download_$(date +%s).txt"
        if $ossutil_cmd cp "oss://$OSS_BUCKET/$test_path" "$download_file" 2>&1; then
            if cmp -s "$test_file" "$download_file"; then
                log "✓ OSS下载测试成功"
            else
                warn "下载文件内容不匹配"
            fi
            rm -f "$download_file"
        else
            warn "OSS下载测试失败"
        fi
        
        rm -f "$test_file"
        return 0
    else
        error "OSS连接测试失败"
        rm -f "$test_file"
        return 1
    fi
}

case "$1" in
    "check")
        check_oss_util
        ;;
    "upload")
        upload_file "$2"
        ;;
    "upload-dir")
        upload_directory "$2"
        ;;
    "info")
        show_instance_info
        ;;
    "config")
        show_config
        ;;
    "test")
        test_oss_connection
        ;;
    *)
        echo "用法: $0 {check|upload <file>|upload-dir <directory>|info|config|test}"
        echo ""
        echo "命令说明:"
        echo "  check         - 检查ossutil工具"
        echo "  upload FILE   - 上传单个文件到OSS"
        echo "  upload-dir DIR - 上传整个目录到OSS"
        echo "  info          - 显示实例信息"
        echo "  config        - 显示OSS配置"
        echo "  test          - 测试OSS连接"
        echo ""
        echo "使用前请确保已配置OSS: $SCRIPTS_DIR/init_oss_config.sh init"
        exit 1
        ;;
esac
